/*
	GameServer.cpp
	(c)2000 Palestar Inc, Richard Lyle
*/

#include "stdafx.h"
#include <stdio.h>
#include <time.h>
#include <Excpt.h>

#include "Debug/Assert.h"
#include "Debug/LogHelper.h"
#include "Debug/ExceptionHandler.h"
#include "Factory/BrokerFolder.h"
#include "Standard/CommandLine.h"
#include "Standard/Time.h"
#include "Standard/Settings.h"
#include "Standard/Process.h"
#include "Game/GameServer.h"

//----------------------------------------------------------------------------

int RunServer( void * pINI )
{
	Event serverStop( CharString().format("StopProcess%u", Process::getCurrentProcessId()) );
	Settings settings( "GameServer", (const char *)pINI );

	CharString logFile = settings.get( "logFile", "GameServer.log" );

	GetErrorOutput().initialize( DebugOutput::RF_DEBUGGER | DebugOutput::RF_LOGFILE, "Error", logFile );
	if ( settings.get( "enableTrace", (dword)0 ) != 0 )
		GetTraceOutput().initialize( DebugOutput::RF_DEBUGGER| DebugOutput::RF_LOGFILE | DebugOutput::RF_RESET_LOGFILE, "Trace", logFile );

	// open the data
	BrokerFolder theData;

	CharString dataFolder = settings.get( "data", ".\\data\\" );
	if (! theData.open( dataFolder , false, false ) )
	{
		LogHelper::log( logFile, CharString().format("Failed to open data directory '%s'", dataFolder) );
		return 0;	// failed to open the data directory
	}

	// load the GameContext
	GameContext::Link universeContext;
	if (! loadResource( settings.get( "context", "Start.prt" ), universeContext ) )
	{
		LogHelper::log( logFile, "Failed to load GameContext!" );
		return 0;	// failed to load GameContext
	}

	GameServer::Context serverContext;
	serverContext.nServerFlags = settings.get( "serverFlags", 2 );
	serverContext.nClientFlags = settings.get( "clientFlags", (dword)0 );
	serverContext.nModFlags = settings.get( "modFlags", MetaClient::MODERATOR|MetaClient::ADMINISTRATOR|MetaClient::DEVELOPER );
	//serverContext.bMaster = settings.get( "master", 1 ) != 0;
	//serverContext.sMasterAddress = settings.get( "masterAddress", "" );
	//serverContext.nMasterPort = settings.get( "masterPort", 9000 );
	serverContext.bPublish = settings.get( "publish", 1 ) != 0;
	serverContext.sMetaAddress = settings.get( "metaAddress", "beta.palestar.com" );
	//serverContext.sMetaAddress = settings.get( "metaAddress", "meta-server.palestar.com" );
	serverContext.nMetaPort = settings.get( "metaPort", 9000 );
	serverContext.nUniverseContext = universeContext.key();
	serverContext.maxPlayers = settings.get( "maxPlayers", 32 );
	serverContext.maxRank = settings.get( "maxRank", CHIEF_MARSHAL );
	serverContext.bBalanced = settings.get( "balanced", 1 ) != 0;
	serverContext.bClan = settings.get( "clan", 1 ) != 0;
	serverContext.bTutorial = settings.get( "tutorial", (dword)0 ) != 0;
	serverContext.user = settings.get( "user", "DSS" );
	serverContext.password = settings.get( "password", "darkspace" );
	serverContext.nSessionId = settings.get( "sessionId", (dword)0 );
	serverContext.gameId = settings.get( "gameId", 1 );
	
	serverContext.sLogFile = settings.get( "logFile", ".\\GameServer.log" );
	serverContext.sLogAddress = settings.get( "logAddress", "" );
	serverContext.nLogPort = settings.get( "logPort", 10000 );

	serverContext.name = settings.get( "name", "GameServer" );
	serverContext.description = settings.get( "description", "" );
	serverContext.address = settings.get( "address", "" );
	serverContext.port = settings.get( "port", 9001 );
	serverContext.maxClients = settings.get( "maxClients", 32 );
	serverContext.nCompression = settings.get( "compression", 6 );
	serverContext.clientsPerThread = settings.get( "clientsPerThread", 8 );
	serverContext.nDisconnectTime = settings.get( "disconnectTime", 120 );
	serverContext.runScript = settings.get( "runScript", "" );
	serverContext.bPersistant = settings.get( "persistant", (dword)0 ) != 0;
	serverContext.sSaveFile = settings.get( "saveFile", ".\\GameServer.wob" );
	serverContext.sStorage = settings.get( "storage", ".\\storage\\" );
	serverContext.bEditor = settings.get("editor", (dword)0 ) != 0;

	// how often to automatically stop the server
	CharString sRestartTimeMask = settings.get( "RestartTimeMask", "" );

	// create the server object
	GameServer theServer;

	// start the server
	if (! theServer.start( serverContext ) )
		return 0;	// failed to start the server

	dword nSeconds = 0;
	Timer secondTimer( 1000 );

	while( theServer.update() )
	{
		if ( nSeconds == 0 && (Time::isTime( Time::seconds(), sRestartTimeMask ) || serverStop.signaled()) )
			nSeconds = settings.get( "ShutdownTime", 60 );

		if ( nSeconds != 0 && secondTimer.signaled() )
		{
			nSeconds--;
			if ( nSeconds == 0 )
				break;			// time to shutdown, exit the while loop...

			if ( (nSeconds > 10 && (nSeconds % 10) == 0) || nSeconds <= 10 )
				theServer.sendChat( CharString().format("SERVER: shutting down in %d seconds...", nSeconds) );
		}
	}

	theServer.stop();

	return 0;
}

//----------------------------------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
#ifndef _DEBUG
	//Core::seekHome();
#endif

	CommandLine cmdLine( lpCmdLine );
	if ( cmdLine.argumentCount() != 1 )
	{
		MessageBox( NULL, TEXT("Usage: GameServer.exe <iniFile>"), TEXT("Invalid Command Line"), MB_OK );
		return 0;
	}

	return HandleException( RunServer, (void *)cmdLine.argument( 0 ) );
}

//----------------------------------------------------------------------------
//EOF
